#include "worktask.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "systemdata.h"
#include "wakeup.h"
#include "delay.h"
#include "powermanage.h"
#include "drv_timer.h"
#include "main.h"
#include "bat_afe.h"

typedef struct{
	uint8_t pre_start_flag;
	uint8_t pre_chg_ok_flag;
	uint16_t pre_chg_time_ms;
}PreChgCtrlData_t;

static PreChgCtrlData_t pre_chg_data = {.pre_start_flag = 0,.pre_chg_ok_flag = 0,.pre_chg_time_ms = 0};
static uint16_t sleep_delay_time_ms = 0;
static SysConfData_t *confinfo = NULL;//系统参数指针
static SysRunData_t  *runinfo = NULL;//系统运行数据指针
static Timer_t		 *work_task_timer_1ms = NULL;//状态切换计时定时器

uint8_t sleep_enter_control(void){
	if(runinfo->batState == chgState || runinfo->batState == dsgState){//如果是充放电状态,不允许休眠
		return 0;
	}else{
		runinfo->sleep_flag = 1;
		return 1;
	}
	
	return 0;
}

static void pre_charge_process(void){
	uint8_t res = 0;
	if(runinfo->sysSwState.bits.SW_PRE == 0){
		afe_prechg_mos_ctrl(true);
	}
	if(pre_chg_data.pre_chg_ok_flag == 0){
		pre_chg_data.pre_start_flag = 1;
		if(pre_chg_data.pre_chg_time_ms >= (uint32_t)confinfo->fctData.preChargeTime.value){
			printf("prepare charge ok!\n");
			pre_chg_data.pre_chg_ok_flag = 1;
			pre_chg_data.pre_start_flag = 0;
			pre_chg_data.pre_chg_time_ms = 0;
		}
	}else{
		pre_chg_data.pre_chg_time_ms = 0;
		pre_chg_data.pre_start_flag = 0;
	}
}

static void pre_charge_time_ctrl(void *data){
	if(pre_chg_data.pre_start_flag == 1){
		pre_chg_data.pre_chg_time_ms += *(uint32_t *)data;
	}else{
		pre_chg_data.pre_chg_time_ms = 0;
	}
}

static void reset_precharge_state(void){
	pre_chg_data.pre_start_flag = 0;
	pre_chg_data.pre_chg_ok_flag = 0;
	pre_chg_data.pre_chg_time_ms = 0;
}

static void state_manager_process(void){
	//汇总充放电相关的故障
	uint8_t chg_error = runinfo->afeProtByte.byte|
						runinfo->curProtByte.bit.chgCUr1Prot|	//充电过流
						runinfo->curProtByte.bit.chgCur2Prot|
						runinfo->curProtByte.bit.chgCur3Prot|
						(bool)runinfo->volProtByte.cellHgVolProt|	//单体过压
						runinfo->volProtByte.volProt.bit.packVolHgProt|	//总压过压
						runinfo->tempProtByte.bit.chgTempLowProt|	//充电低温
						runinfo->tempProtByte.bit.chgTempHgProt| 	//充电过温
						runinfo->tempProtByte.bit.mosTempHgProt;	//MOS过温
	
	uint8_t dsg_error = runinfo->afeProtByte.byte|
						runinfo->curProtByte.bit.disCur1Prot|	//放电过流
						runinfo->curProtByte.bit.disCur2Prot|
						runinfo->curProtByte.bit.disCur3Prot|
						runinfo->curProtByte.bit.disCur4Prot|
						runinfo->curProtByte.bit.shortCurProt| 	//短路
						(bool)runinfo->volProtByte.cellLowVolProt|	//单体欠压
						runinfo->volProtByte.volProt.bit.packVolLowProt|	//总压欠压
						runinfo->tempProtByte.bit.disTempLowProt|	//放电低温
						runinfo->tempProtByte.bit.disTempHgProt| 	//放电过温
						runinfo->tempProtByte.bit.mosTempHgProt;	//MOS过温
	//先通过电流、钥匙信号判断充放电状态
	uint8_t chg_flag = 0;
	uint8_t dsg_flag = 0;
	int16_t wakeupCur = confinfo->fctData.wakeupCurrent.value;
	if(abs(runinfo->batCur) > confinfo->fctData.wakeupCurrent.value){//电流大于唤醒值
		if(runinfo->batCur > 0){//电流为正
			chg_flag = 1;
		}else{
			dsg_flag = 1;
		}
	}else{
		chg_flag = 0;
		dsg_flag = 0;
	}
	//根据充电允许、故障等信息，控制充电MOS状态
	if(dsg_flag == 1 || (runinfo->sysSwState.bits.SW_CHG_EN == 1 && chg_error == 0)){
		if(confinfo->fctData.chgLimitMode == 0){
			afe_chg_mos_ctrl(true);
		}else if(confinfo->fctData.chgLimitMode == 1){
			if(runinfo->comLinkState.Bits.rs485_obc_link == 0){//如果与充电机连接断开
				//打开限流、关闭充电mos
				//afe_chglimit_mos_ctrl(true);
				afe_chg_mos_ctrl(false);
			}else{//与充电机通信正常
				afe_chg_mos_ctrl(true);
				//afe_chglimit_mos_ctrl(false);
			}
		}
		
	}else{
		afe_chg_mos_ctrl(false);
	}
	//根据放电允许、故障等信息，控制放电MOS状态
	if(chg_flag == 1){
		afe_dsg_mos_ctrl(true);
	}else if(runinfo->sysSwState.bits.SW_DSG_EN == 1 && dsg_error == 0){
		if(pre_chg_data.pre_chg_ok_flag == 0){
			pre_charge_process();
		}else{
			afe_dsg_mos_ctrl(true);
			afe_prechg_mos_ctrl(false);
		}
	}else{
		afe_dsg_mos_ctrl(false);
		reset_precharge_state();
		afe_prechg_mos_ctrl(false);
	}
	//更新电池当前状态
	if(chg_flag == 1){
		runinfo->batState = chgState;
	}else if(dsg_flag == 1){
		runinfo->batState = dsgState;
	}else if(runinfo->tempProtByte.byte==0&&runinfo->curProtByte.byte==0&&
	runinfo->volProtByte.volProt.byte==0&&runinfo->afeProtByte.byte==0&&
	runinfo->volProtByte.cellHgVolProt==0&&runinfo->volProtByte.cellLowVolProt==0){
		runinfo->batState = stdState;
	}else{
		runinfo->batState = errState;
	}
	if(runinfo->tempProtByte.byte != 0x00||runinfo->curProtByte.byte!=0||
		runinfo->volProtByte.volProt.byte!=0||runinfo->afeProtByte.byte!=0||
	runinfo->volProtByte.cellHgVolProt!=0||runinfo->volProtByte.cellLowVolProt!=0){
		saveSystemErrorRecord();//保存故障记录
	}else{
		clearLastError();
	}
}

static void sleep_process(void){
	afe_dsg_mos_ctrl(false);
	afe_prechg_mos_ctrl(false);
	afe_chg_mos_ctrl(false);
	runinfo->batState = slpState;
	if(sleep_delay_time_ms <= 600){//比上位机的查询周期多100ms
		return;
	}
	sleep_delay_time_ms = 0;
	system_sleep_enter();
	runinfo->sleep_flag = 0;
	runinfo->poweroff_flag = 0;
}

static void sleep_delay_ctrl(void *data){
	if(runinfo->sleep_flag == 1 || runinfo->poweroff_flag == 1){
		sleep_delay_time_ms += *(uint32_t *)data;
	}else{
		sleep_delay_time_ms = 0;
	}
}

#define CELL_POWEROFF_TIME	(1000*60*30)	//30分钟

static void auto_poweroff_ctrl(void *data){
		
	static uint32_t power_enter_wait_time = 0;
	//没有充放电且单体最低电压低于关机电压，开始计时
	if((runinfo->batMinVol < confinfo->fctData.poweroff_vol.value) && (runinfo->batState != chgState) && (runinfo->batState != dsgState)){
		power_enter_wait_time += *(uint32_t *)data;
	}else{
		power_enter_wait_time = 0;
	}
	if(power_enter_wait_time >= CELL_POWEROFF_TIME){//30分钟
		if(runinfo->sysSwState.bits.SW_OTA != 0){
			power_enter_wait_time = CELL_POWEROFF_TIME;
			return;
		}
		power_enter_wait_time = 0;
		runinfo->poweroff_flag = 1;
	}
}

void work_task_process(void){
	if(runinfo->sleep_flag == 0 && runinfo->poweroff_flag == 0){
		state_manager_process();
	}else{
		sleep_process();
	}
}
	
static void work_timer_1ms_callback(void *data){
	pre_charge_time_ctrl(data);
	auto_poweroff_ctrl(data);
	sleep_delay_ctrl(data);
}

void work_task_init(void){
	confinfo = getSysConfData();
	runinfo = getSysRunData();
	runinfo->active_flag = 0;
	runinfo->batState = stdState;
	work_task_timer_1ms = timer_create(work_timer_1ms_callback,1);
	timer_start(work_task_timer_1ms);
}
